package org.latestbit.smartobjects.examples.android.chat;

import java.io.IOException;

import org.latestbit.smartobjects.*;
import org.latestbit.smartobjects.ISmartBus.ConnectMode;
import org.latestbit.smartobjects.examples.android.chat.client.ChatClientImpl;
import org.latestbit.smartobjects.examples.android.chat.client.CommandLineOptions;
import org.latestbit.smartobjects.examples.chat.ChatMessage;
import org.latestbit.smartobjects.examples.chat.ChatService;
import org.latestbit.smartobjects.examples.chat.IChatEventsSyncSmartObject;
import org.latestbit.smartobjects.examples.chat.IChatService;
import org.latestbit.smartobjects.exceptions.SmartBusSystemException;
import org.latestbit.smartobjects.network.IEndpointLocation;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class ChatMainActivity extends Activity {
	private ISmartBus bus;
	private IChatService service;
	private CommandLineOptions options = new CommandLineOptions();
	
	protected static final int DIALOG_ERROR = 0;
	protected ChatClientImpl client = null;
	protected Exception lastError;
	private Handler handler = new Handler();

	private void writeChatLog(final String string) {
		final EditText locationText = (EditText)findViewById(R.id.ChatTextLog);			
		if(locationText!=null) {
			locationText.append(string+"\n");
		}
	}
	private void writeChatLog(final String string, boolean postInvalidate) {		
		if(postInvalidate) {
			handler.post(new Runnable() {	
					@Override
					public void run() {
						writeChatLog(string);
					}					
				}
			);				
		}
		else
			writeChatLog(string);
	}
	
	private IChatEventsSyncSmartObject chatRoomNotificationsHandler = new IChatEventsSyncSmartObject() {

		@Override
		public void destroy() {
			
		}

		
		@Override
		public void onSystemMessage(ChatMessage message)
				throws SmartBusSystemException {
			writeChatLog("[SM] "+message.getValue(), true);
		}


		@Override
		public void onUserMessage(String login, ChatMessage message)
				throws SmartBusSystemException {
			writeChatLog(login+": "+message.getValue(), true);
		}

		@Override
		public void onSessionWasClosed() throws SmartBusSystemException {
			setContentView(R.layout.chatform);
		}
		
	};
	
	private IRemoteSmartObjectAvailabilityListener<IRemoteSmartObject> availabilityListener = new IRemoteSmartObjectAvailabilityListener<IRemoteSmartObject>() {

		@Override
		public void onAvailable(IRemoteSmartObject object) {
			object.delAvailabilityListener(this);
			
			handler.post(new Runnable() {	
				@Override
				public void run() {
					try {
						client = new ChatClientImpl(options, service, chatRoomNotificationsHandler);
						client.start();						
						closeProgressDialog();
						showChatForm();
					}
					catch(Exception ex) {
						lastError = ex;
						closeProgressDialog();
						showDialog(DIALOG_ERROR);
					}					
				}
			});				
		}

		@Override
		public void onUnavailable(IRemoteSmartObject object) {			
		}
		
	};
	private ProgressDialog progressDialog;
		 
	public void resolveService() throws Exception {
			
			bus = new SmartBus();
			// bus.setSyncConnectTimeout(15);
			bus.setConnectMode(ConnectMode.ASYNC_CONNECT_MODE);
			IEndpointLocation location = bus.createEndpointLocation( options.getLocation() );
			service = new ChatService();
			service.addAvailabilityListener(this.availabilityListener);
			service.getDefaultRequestContext().setMaxResponseTimeoutInSec(25);
			service.resolve(bus, location);
			handler.postDelayed(new Runnable() {

				@Override
				public void run() {
					// TODO Auto-generated method stub
					if(client==null) {
						closeProgressDialog();
						lastError = new IOException("Connection timeout");
						showDialog(DIALOG_ERROR);
					}
				}
				
			}, 15000);
	}
	
	public void showProgressDialog() {
		this.progressDialog = ProgressDialog.show(ChatMainActivity.this, "", "Please wait for few seconds...", true);		
	}
	
	public void closeProgressDialog() {
		if(this.progressDialog!=null)
			this.progressDialog.dismiss();
	}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
        java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
                
        showConnectionForm();        
    }
    
    private void showConnectionForm() {
    	setContentView(R.layout.connectionform);
        Button connectButton = (Button)findViewById(R.id.ConnectButton);

        connectButton.setOnClickListener(new OnClickListener() {        	
			

			public void onClick(View v) {
				try { 					
					showProgressDialog();
					EditText locationText = (EditText)findViewById(R.id.LocationAddressText);
					options.setLocation(locationText.getText().toString());
					resolveService();					
				}
				catch(Exception ex) {
					lastError = ex;					
					showDialog(DIALOG_ERROR);					
				}
				
			}
			
			
		});
                
	}

	private void showChatForm() {
		setContentView(R.layout.chatform);
		
		Button logoutButton = (Button)findViewById(R.id.LogoutButton);

        logoutButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				service.destroy();
				bus.destroy();				
				ChatMainActivity.this.finish();				
			}
        	
        });
        
		Button sendTextButton = (Button)findViewById(R.id.SendTextButton);

		sendTextButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				EditText userInput = (EditText)findViewById(R.id.EnterText);
				client.sendUserInput(userInput.getText().toString());
				writeChatLog("You: "+userInput.getText().toString(), false);
				userInput.setText("");
			}
        	
        });
        
	}

	@Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case DIALOG_ERROR: {
            	AlertDialog.Builder builder = new AlertDialog.Builder(this);
            	builder.setMessage("Error! "+lastError.getMessage())
            	       .setCancelable(false)
            	       .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            	           public void onClick(DialogInterface dialog, int id) {
            	        	   showConnectionForm();
            	           }
            	       }); 
                return builder.create();
            }            
        }
        return null;
    }
	
	
}